home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994…tember: Reference Library / Dev.CD Sep 94.toast / Periodicals / develop / develop Issue 18 / develop 18 code / OSA Sample / Sources / ScriptableObjects.cp < prev    next >
Encoding:
Text File  |  1994-02-04  |  14.6 KB  |  709 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        ScriptableObjects.cp
  3.  
  4.     Contains:    Script handling & OSA interface
  5.  
  6.     Developed by:    
  7.         
  8.         Paul G Smith (commstalk hq & Full Moon Software, Inc)
  9.         
  10.         you can leave messages at (UK): 0727 844232; (US): 408 253 7199
  11.         BUT I prefer to be contacted by e-mail
  12.         AppleLink:     SMITH.PG
  13.         Internet:     SMITH.PG@applelink.apple.com
  14.         
  15.         "SimpliFace" Sample code to accompany develop article
  16.         on techniques for embedding scripts in applications.
  17.  
  18. */
  19.  
  20.  
  21. #include "ScriptableObjects.h"
  22. #include "SimpliFaceCommon.h"
  23.  
  24. #ifndef __STDIO__
  25. #include <StdIO.h>
  26. #endif
  27.  
  28. #ifndef __LIMITS__
  29. #include <Limits.h>
  30. #endif
  31.  
  32. #ifndef __ERRORS__
  33. #include <Errors.h>
  34. #endif
  35.  
  36. #ifndef __RESOURCES__
  37. #include <Resources.h>
  38. #endif
  39.  
  40. #ifndef __TOOLUTILS__
  41. #include <ToolUtils.h>
  42. #endif
  43.  
  44. #ifndef __FOLDERS__
  45. #include <Folders.h>
  46. #endif
  47.  
  48. #ifndef __PLSTRINGFUNCS__
  49. #include <PLStringFuncs.h>
  50. #endif
  51.  
  52. #ifndef __WINDOWS__
  53. #include <Windows.h>
  54. #endif
  55.  
  56. #ifndef __PACKAGES__
  57. #include <Packages.h>
  58. #endif
  59.  
  60. #ifndef __PROCESSES__
  61. #include <Processes.h>
  62. #endif
  63.  
  64. #ifndef __PLSTRINGFUNCS__
  65. #include <PLStringFuncs.h>
  66. #endif
  67.  
  68. #ifndef __AEOBJECTS__
  69. #include <AEObjects.h>
  70. #endif
  71.  
  72. #ifndef __ASDEBUGGING__
  73. #include <ASDebugging.h>
  74. #endif
  75.  
  76. #ifndef __ASREGISTRY__
  77. #include <ASRegistry.h>
  78. #endif
  79.  
  80. #ifndef __SCRIPTUTILS__
  81. #include "ScriptUtils.h"
  82. #endif
  83.  
  84. #ifndef __SIMPLIFACE__
  85. #include "SimpliFace.h"
  86. #endif
  87.  
  88. #ifndef __AEOMTOKENS__
  89. #include "ObjModelTokens.h"
  90. #endif
  91.  
  92. #ifndef __AEOMEVENTS__
  93. #include "ObjModelEvents.h"
  94. #endif
  95.  
  96.  
  97. #include "DebugTrace.h"
  98.  
  99. #pragma trace off
  100.  
  101. // globals
  102.  
  103.  
  104. TScriptAdministrator*    gScriptAdministrator = NULL;
  105. ComponentInstance        gScriptingComponent = NULL;
  106. AEAddressDesc            gSelfAddress;
  107. ProcessSerialNumber        gSelfPSN;
  108.  
  109.  
  110. #ifndef kComponentNotFound
  111. #define kComponentNotFound -1
  112. #endif
  113.     
  114.  
  115.  
  116.  
  117. OSAError GetOSAerrorInfo(ComponentInstance scriptingSystem,
  118.                              OSAError *errNum, char *errStr)
  119. {
  120.     OSAError     err = 0;
  121.     AEDesc        infoDesc;
  122.     
  123.     *errNum = 0;
  124.     
  125.     err = OSAScriptError(scriptingSystem, kOSAErrorMessage,
  126.                          typeChar, &infoDesc);
  127.     if (!err)
  128.         GetPStringFromDescriptor(&infoDesc, errStr);
  129.         
  130.     err = OSAScriptError(scriptingSystem, kOSAErrorNumber,
  131.                          typeShortInteger, &infoDesc);
  132.     if (!err)
  133.         GetLongIntFromDescriptor(&infoDesc, errNum);
  134.  
  135.     return err;
  136. }
  137.  
  138.  
  139.  
  140. void DumpOSAerrorInfo(ComponentInstance scriptingSystem, OSAError err)
  141. {
  142.     char        message[256];
  143.     OSAError    newerr = 0, errNum;
  144.     
  145.     if (err == errOSAScriptError)
  146.     {
  147.         memset(message, 0, 256);
  148.         
  149.         newerr = GetOSAerrorInfo(scriptingSystem, &errNum, message);
  150.     
  151.         if (!newerr /*&& errNum*/ )
  152.         {
  153.             printf("DumpOSAerrorInfo: errNum = %ld\n", errNum);
  154.             printf("%s\n", &message[1]);
  155.         }
  156.         else
  157.             printf("DumpOSAerrorInfo failed: err = %ld\n", err);
  158.     }
  159. }
  160.  
  161.  
  162.  
  163.  
  164.  
  165.  
  166. pascal OSErr StdActiveProc(long refCon)
  167. {
  168.     if (gSimpliFace && gScriptAdministrator)
  169.     {
  170.         if (!gScriptAdministrator->StartupScriptIsRunning())
  171.             gSimpliFace->InEventLoop();
  172.     }
  173.     return 0;
  174. }
  175.  
  176.  
  177. /*
  178.     Name:   InitOSAScripting
  179.     Purpose:Connects to the AppleScript component.
  180. */
  181. OSAError InitOSAScripting(void)
  182. {
  183.     OSAError                 err = 0;
  184.     ComponentDescription     descr;
  185.     Component               aComponent;
  186.     ProcessSerialNumber        aSelfPSN;
  187.     ComponentInstance         aScriptingComponent;
  188.     AEAddressDesc            aSelfAddress;    // A self-addressed address descriptor record
  189.     
  190.      aSelfPSN.highLongOfPSN = 0;
  191.      aSelfPSN.lowLongOfPSN = kCurrentProcess;        //* Use this instead of GetCurrentProcess *//
  192.     AECreateDesc(typeProcessSerialNumber, (Ptr)&aSelfPSN,
  193.                  sizeof(ProcessSerialNumber), &aSelfAddress);
  194.  
  195.     descr.componentType         = kOSAComponentType;
  196.     descr.componentSubType      = (OSType) 0;
  197.     descr.componentManufacturer = (OSType) 0;
  198.     descr.componentFlags        = kOSASupportsCompiling + 
  199.                                   kOSASupportsGetSource + 
  200.                                   kOSASupportsConvenience + 
  201.                                   kOSASupportsEventHandling;
  202.     descr.componentFlagsMask    = descr.componentFlags;
  203.     
  204.     aComponent = FindNextComponent(nil, &descr);
  205.         
  206.     if (!aComponent)
  207.         return(kComponentNotFound);
  208.     else
  209.     {
  210.         aScriptingComponent = OpenComponent(aComponent);
  211.                                                                                                 
  212.         if (!aScriptingComponent)
  213.             return(kComponentNotFound);
  214.  
  215.         if (aScriptingComponent) 
  216.             err = OSASetActiveProc(aScriptingComponent, 
  217.                                      (OSAActiveProcPtr)&StdActiveProc, 0);
  218.     }
  219.         
  220.     gScriptingComponent = aScriptingComponent;
  221.     gSelfAddress = aSelfAddress;
  222.     gSelfPSN = aSelfPSN;
  223.     
  224.     return err;
  225. }
  226.  
  227.  
  228. /*
  229.     Name    : CloseOSAScripting
  230.     Purpose : Shutdown of OSA scripting capabilities
  231. */
  232. OSAError CloseOSAScripting(void)
  233. {
  234.     OSAError err = noErr;
  235.     
  236.     if (gScriptingComponent)
  237.     {
  238.         err = CloseComponent(gScriptingComponent);
  239.         gScriptingComponent = NULL;
  240.     }
  241.     
  242.     return err;
  243. }
  244.  
  245.  
  246.  
  247. OSAError StartScriptAdministrator(void)
  248. {
  249.     OSAError    err = InstallEventHandlers();
  250.     
  251.     if (!err)
  252.         err = SFinitAEobjects();
  253.     if (!err)
  254.         err = InitOSAScripting();
  255.     
  256.     if (!err)
  257.         gScriptAdministrator = new TScriptAdministrator;
  258.     
  259.     return err;
  260. }
  261.  
  262. OSAError StopScriptAdministrator(void)
  263. {
  264.     OSAError    err = noErr;
  265.     
  266.     if (gScriptAdministrator)
  267.     {
  268.         delete gScriptAdministrator;
  269.         gScriptAdministrator = NULL;
  270.     }
  271.     
  272.     err = SFendAEobjects();
  273.     err = DeInstallEventHandlers();
  274.     err = CloseOSAScripting();
  275.         
  276.     return err;
  277. }
  278.  
  279.  
  280.  
  281. /*******************************************************************************
  282. ** PUBLIC Constructor/Destructor
  283. ********************************************************************************/
  284.  
  285. TScriptAdministrator::TScriptAdministrator()
  286. {
  287.     fStartupScriptRunning = false;
  288. }
  289.  
  290.  
  291. TScriptAdministrator::~TScriptAdministrator(void)
  292. {
  293. }
  294.  
  295.  
  296.  
  297. void TScriptAdministrator::RunStartupScript(void)
  298. {
  299.     if (fStartupScriptRunning)
  300.         printf("•TScriptAdministrator::RunStartupScript(): attempt to run script recursively\n");
  301.     else
  302.     {
  303.         Str255                fileName;
  304.         short                appVRefNum;
  305.         long                appDirID;
  306.         OSAError            err = GetCurrentAppFileSpec(&appVRefNum, &appDirID,
  307.                                                         (StringPtr)&fileName);
  308.         
  309.         printf("TScriptAdministrator::RunStartupScript()\n");
  310.         
  311.         fStartupScriptRunning = true;
  312.     
  313.         if (!err)
  314.         {
  315.             FSSpec                 theFileSpec;
  316.             OSAID                startupScript = kOSANullScript;
  317.     
  318.             GetIndString(fileName, kSimpliFaceBuzzwords, kStartupScriptFileName);
  319.             
  320.             theFileSpec.vRefNum = appVRefNum;
  321.             theFileSpec.parID = appDirID;
  322.             PLstrcpy((StringPtr)&(theFileSpec.name), (ConstStr255Param)fileName);
  323.             
  324.             err = LoadScriptFromFile(&theFileSpec, &startupScript);
  325.             
  326.             if (!err && startupScript != kOSANullScript)
  327.             {
  328.                 OSAID                resultID = kOSANullScript;
  329.     
  330.                 err = OSAExecute(gScriptingComponent, startupScript,
  331.                                     kOSANullScript, kOSAModeNull, &resultID);                    
  332.                 if (err)
  333.                     DumpOSAerrorInfo(gScriptingComponent, err);
  334.                 else
  335.                 {
  336.                     AEDesc        displayData;
  337.                     
  338.                     printf("TScriptAdministrator::RunStartupScript() succeeded, ");
  339.                     
  340.                     if (resultID != kOSANullScript)
  341.                     {
  342.                         printf("with result: ");
  343.                         err = OSADisplay(gScriptingComponent, resultID, 
  344.                                             typeChar, kOSAModeNull, &displayData);
  345.                         if (!err && displayData.dataHandle)
  346.                         {
  347.                             short    zero = 0;
  348.                             Handle    h = displayData.dataHandle;
  349.                             
  350.                             PtrAndHand(&zero, h, 1);    // shove a zero on the end for stdio
  351.                             HLock(h);
  352.                             printf((char*)*h);
  353.                             HUnlock(h);
  354.                             AEDisposeDesc(&displayData);
  355.                         }
  356.                     }
  357.                     else
  358.                         printf("no result was returned");
  359.                     printf("\n");
  360.                 }
  361.                     
  362.                 OSADispose(gScriptingComponent, startupScript);
  363.                 OSADispose(gScriptingComponent, resultID);
  364.             }
  365.             else
  366.                 printf("Failed to load startup script from file, err = %d\n", err);
  367.         }
  368.         else
  369.             printf("Failed to establish current directory, err = %d\n", err);
  370.         
  371.         fStartupScriptRunning = false;
  372.     }
  373. }
  374.  
  375.  
  376. OSAError TScriptAdministrator::DoScript(AEDesc *scriptDesc, AEDesc *resultDesc)
  377. {
  378.     OSAError        err = errAEEventNotHandled;
  379.  
  380.     if (scriptDesc && (scriptDesc->descriptorType == typeChar
  381.                         || scriptDesc->descriptorType == typeIntlText))
  382.     {
  383.         OSAID    resultID = kOSANullScript;
  384.         
  385.         err = OSACompileExecute(gScriptingComponent, scriptDesc,
  386.                                 kOSANullScript, kOSAModeAlwaysInteract, 
  387.                                 &resultID);
  388.         if (err)
  389.             DumpOSAerrorInfo(gScriptingComponent, err);
  390.         else if (resultID != kOSANullScript)
  391.             err = OSACoerceToDesc(gScriptingComponent, resultID, typeWildCard,
  392.                                      kOSAModeNull, resultDesc);
  393.  
  394.         OSADispose(gScriptingComponent, resultID);
  395.     }
  396.     
  397.     return err;
  398. }
  399.  
  400.  
  401. OSAID    TScriptAdministrator::GetAttachedScript(TScriptableObject* theObj)
  402. {
  403.     if (theObj)
  404.         return theObj->GetObjScript();
  405.     else
  406.         return kOSANullScript;
  407. }
  408.  
  409.  
  410. OSAError    TScriptAdministrator::ReleaseAttachedScript(TScriptableObject* theObj)
  411. {
  412.     return noErr;
  413. }
  414.  
  415.  
  416. OSAError    TScriptAdministrator::LoadScriptFromFile(FSSpec *fileSpec, OSAID *theScriptID)
  417. {
  418.     short        fileRef = FSpOpenResFile(fileSpec, fsRdPerm);
  419.     OSAError    err = ResError();
  420.  
  421.     if (!err)
  422.     {
  423.         Handle    h = Get1Resource(kOSAScriptResourceType, 128);
  424.         
  425.         if (h)
  426.         {
  427.             AEDesc    scriptData;
  428.             
  429.             scriptData.descriptorType = typeOSAGenericStorage;
  430.             scriptData.dataHandle = h;
  431.             
  432.             err = OSALoad(gScriptingComponent, &scriptData, kOSAModeNull,
  433.                             theScriptID);
  434.                             
  435.             ReleaseResource(scriptData.dataHandle);
  436.         }
  437.         CloseResFile(fileRef);
  438.     }
  439.     
  440.     return err;
  441. }
  442.  
  443.  
  444. OSAError    TScriptAdministrator::SaveScriptToFile(FSSpec *fileSpec, OSAID theScriptID)
  445. {
  446.     FSpCreateResFile(fileSpec, 'ToyS', 'osas', smRoman); 
  447.     // ignore errors - let's see if we can open the file, now
  448.     
  449.     short        fileRef = FSpOpenResFile(fileSpec, fsRdPerm);
  450.     OSAError    err = ResError();
  451.  
  452.     if (!err)
  453.     {
  454.         AEDesc    scriptData;
  455.  
  456.         InitAEDescs(&scriptData, kEndOfList);
  457.         
  458.         err = OSAStore(gScriptingComponent, theScriptID, typeOSAGenericStorage, 
  459.                         kOSAModeDontStoreParent, &scriptData);
  460.         
  461.         if (!err && scriptData.dataHandle)
  462.         {
  463.             FInfo        fndrInfo;
  464.             Handle        h = Get1Resource(kOSAScriptResourceType, 128);
  465.             
  466.             if (h)
  467.             {    // delete old script resource
  468.                 RmveResource(h);
  469.                 h = NULL;
  470.             }
  471.             
  472.             AddResource(scriptData.dataHandle, kOSAScriptResourceType, 128, 
  473.                         (ConstStr255Param)"");
  474.             
  475.             err = FSpGetFInfo(fileSpec, &fndrInfo);
  476.             if (!err)
  477.             {
  478.                 fndrInfo.fdType = 'osas';
  479.                 fndrInfo.fdCreator = 'ToyS';
  480.                 err = FSpSetFInfo(fileSpec, &fndrInfo);
  481.             }
  482.         }
  483.         else if (!err)
  484.             err = -194; // addResFailed
  485.  
  486.         CloseResFile(fileRef);
  487.     }
  488.  
  489.     return err;
  490. }
  491.  
  492.  
  493.  
  494. /*******************************************************************************
  495. ** PUBLIC Constructor/Destructor
  496. ********************************************************************************/
  497.  
  498. TScriptableObject::TScriptableObject()
  499. {
  500.     fAttachedScript = kOSANullScript;
  501. }
  502.  
  503. TScriptableObject::~TScriptableObject(void)
  504. {
  505.     if (fAttachedScript != kOSANullScript && gScriptingComponent)
  506.     {
  507.         OSADispose(gScriptingComponent, fAttachedScript);
  508.     }
  509. }
  510.  
  511.  
  512. OSErr TScriptableObject::CountElements(DescType desiredClass, long *result)
  513. {
  514.     OSErr             err = errAEEventNotHandled;
  515.     
  516.     return err;
  517. }
  518.  
  519.                                     
  520. OSErr TScriptableObject::CompareWith   (DescType comparisonOperator,
  521.                                     const TScriptableObject *objToCompare,
  522.                                     Boolean *result)
  523. {
  524.     return errAEEventNotHandled;
  525. }
  526.         
  527.         
  528.             
  529. OSErr TScriptableObject::ResolveContainer(TScriptableObject **theContainerObj)
  530. {
  531.     OSErr             err = errAEEventNotHandled;
  532.  
  533.     return err;
  534. }
  535.  
  536.                                     
  537. OSErr TScriptableObject::ResolveElementByName(DescType desiredClass,
  538.                                         CStr255& nameStr,
  539.                                         TScriptableObject **theResultObj)
  540. {
  541.     OSErr             err = errAEEventNotHandled;
  542.  
  543.     return err;
  544. }
  545.  
  546.                                     
  547. OSErr TScriptableObject::ResolveElementByIndex(DescType desiredClass,
  548.                                         short theIndex,
  549.                                         TScriptableObject **theResultObj)
  550. {
  551.     OSErr             err = errAEEventNotHandled;
  552.  
  553.     return err;
  554. }
  555.  
  556.  
  557. // data handling
  558.  
  559. OSErr TScriptableObject::OpenObject(void)
  560. {
  561.     OSErr                 err = errAEEventNotHandled;
  562.     
  563.     printf("TScriptableObject::OpenObject(): err = %d\n", err);
  564.     return err;
  565. }
  566.  
  567. OSErr TScriptableObject::CloseObject(void)
  568. {
  569.     OSErr                 err = errAEEventNotHandled;
  570.  
  571.     return err;
  572. }
  573.                                     
  574. OSErr TScriptableObject::GetData  (AEDesc *result)
  575. {
  576. //    OSErr                 err = AECreateList(NULL, 0, true, result);
  577.     OSErr                 err = errAEEventNotHandled;
  578.         
  579.     return err;
  580. }
  581.                                             
  582. OSErr TScriptableObject::SetData  (const AEDesc *theData)
  583. {
  584.     //     data is AERecord; for each field of record:
  585.     //        save it as property of object with keyword = propertyID
  586.     OSAError        err = noErr;
  587.     long            numItems = 0;
  588.     
  589.     err = AECountItems(theData, &numItems);
  590.  
  591.     while (!err && numItems > 0)
  592.     {
  593.         AEKeyword        theKeyword;
  594.         AEDesc            theProperty;
  595.         
  596.         InitAEDescs(&theProperty, kEndOfList);
  597.         err = AEGetNthDesc(theData, numItems, typeWildCard, 
  598.                             &theKeyword, &theProperty);
  599.         if (!err && theKeyword != typeNull)
  600.             SetProperty(theKeyword, &theProperty);
  601.         DisposeAEDescs(&theProperty, kEndOfList);
  602.         numItems--;
  603.     }
  604.  
  605.     return err;
  606. }    
  607.  
  608. OSErr TScriptableObject::GetProperty  (DescType propertyID, DescType wantType, AEDesc *result)
  609. {
  610.     OSErr                 err = errAEEventNotHandled;
  611.  
  612.     switch (propertyID)
  613.     {
  614.     case pScript:
  615.         if (fAttachedScript != kOSANullScript)
  616.         {
  617.             printf("TScriptableObject::GetProperty(): get script as type '%.4s'\n",
  618.                     (char*)&wantType);
  619.             if (wantType == typeChar || wantType == typeIntlText)
  620.             {    // if caller wants text, we need to de-compile the script
  621.                 err = (OSErr)OSAGetSource(gScriptingComponent, fAttachedScript, 
  622.                                             wantType, result);
  623.             }
  624.             else
  625.             {
  626.                 if (wantType == typeWildCard)
  627.                     wantType = typeOSAGenericStorage;
  628.                     
  629.                 err = (OSErr)OSAStore(gScriptingComponent, fAttachedScript, 
  630.                                     wantType, kOSAModeDontStoreParent, result);
  631.             }
  632.         }
  633.         break;
  634.     }
  635.     
  636.     return err;
  637. }
  638.                                             
  639. OSErr TScriptableObject::SetProperty  (DescType propertyID, const AEDesc *theData)
  640. {
  641.     OSAError         err = errAEEventNotHandled;
  642.     
  643.     if (theData && theData->dataHandle)
  644.         printf("TScriptableObject::SetProperty: dataType=%.4s, size=%ld\n",
  645.                 &(theData->descriptorType), GetHandleSize(theData->dataHandle));
  646.     
  647.     switch (propertyID)
  648.     {
  649.     case pScript:
  650.         OSAID theValueID = kOSANullScript;
  651.         
  652.         if (theData->descriptorType == typeChar
  653.             || theData->descriptorType == typeIntlText)
  654.             err = OSACompile(gScriptingComponent, theData, 
  655.                              kOSAModeCompileIntoContext, &theValueID);
  656.         else // it it's not text, we assume the script is already compiled
  657.             err = OSALoad(gScriptingComponent, theData, 
  658.                             kOSAModeNull, &theValueID);
  659.         if (!err)
  660.         {
  661.             if (fAttachedScript != kOSANullScript)
  662.                 OSADispose(gScriptingComponent, fAttachedScript);
  663.             fAttachedScript = theValueID;
  664.         }
  665.         break;
  666.     }
  667.     
  668.     return (OSErr)err;
  669. }    
  670.  
  671.  
  672. OSErr TScriptableObject::CreateNewElement    (DescType desiredClass,
  673.                                         DescType position,
  674.                                         AEDesc *theData,
  675.                                         AERecord *theProperties,
  676.                                         TScriptableObject *theContainerObj,
  677.                                         TScriptableObject **theNewObj)
  678. {
  679.     OSErr             err = errAEEventNotHandled;
  680.  
  681.     return err;
  682. }    
  683.  
  684.  
  685. OSErr TScriptableObject::DeleteObject  (void)
  686. {
  687.     return errAEEventNotHandled;
  688. }
  689.  
  690.  
  691. OSErr TScriptableObject::GetObjectSpecifier  (AEDesc *result)
  692. {
  693.     return errAEEventNotHandled;
  694. }    
  695.  
  696.  
  697. OSErr TScriptableObject::GetTargetObjectSpecifier  (EventRecord& theEvent, AEDesc *result)
  698. {
  699.     return errAEEventNotHandled;
  700. }    
  701.  
  702.  
  703.  
  704. // to be added: virtual handlers for                                        
  705. //         does element exist
  706. //        clone object
  707.  
  708.  
  709.